package com.coincalf.exchange.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.coincalf.exchange.entity.Market;
import com.coincalf.exchange.entity.TradeArea;
import com.coincalf.exchange.mapper.MarketMapper;
import com.coincalf.exchange.service.MarketService;
import com.coincalf.exchange.service.TradeAreaService;
import com.coincalf.framework.constants.Constant;
import com.coincalf.framework.dto.ForexMarketDTO;
import com.coincalf.framework.enums.BaseStatus;
import com.coincalf.framework.enums.MarketType;
import com.coincalf.framework.utils.GsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 交易对配置信息 服务实现类
 * </p>
 *
 * @author qiang
 * @since 2018-05-12
 */
@Service
public class MarketServiceImpl extends ServiceImpl<MarketMapper, Market> implements MarketService, Constant {

    @Autowired
    private TradeAreaService tradeAreaService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 根据交易市场类型查询（缓存2分钟）
     *
     * @param marketType 交易区域类型
     * @return
     */
    @Override
    public List<Market> queryMarketListFromCache(MarketType marketType) {
        EntityWrapper<Market> wrapper = new EntityWrapper<>();
        wrapper.eq("type", marketType.getCode());
        wrapper.eq("status", BaseStatus.EFFECTIVE.getCode());
        wrapper.orderBy("sort", true);
        return baseMapper.selectList(wrapper);
    }

    /**
     * 基础货币兑（USDT或BTC）汇率
     *
     * @param market 交易对
     * @return
     */
    @Override
    public BigDecimal getBaseCoinToPriceCoinRate(Market market) {
        BigDecimal baseRate;
        ForexMarketDTO forexMarket = this.queryForexMarketFromCache(market.getSymbol());
        if (Optional.ofNullable(forexMarket).isPresent()) {
            baseRate = forexMarket.getAskPrice();
        } else {
            baseRate = market.getOpenPrice();
        }
        TradeArea tradeArea = tradeAreaService.queryTradeAreaFromCache(market.getTradeAreaId());
        // 报价货币
        if (!market.getBuyCoinId().equals(tradeArea.getCoinId())) {
            baseRate = BigDecimal.ONE;
        }
        return baseRate;
    }

    /**
     * 报价货币兑（USDT或BTC）汇率
     *
     * @param market 交易对
     * @return
     */
    @Override
    public BigDecimal getPriceCoinToBaseCoinRate(Market market) {
        BigDecimal baseRate;
        ForexMarketDTO forexMarket = this.queryForexMarketFromCache(market.getSymbol());
        if (Optional.ofNullable(forexMarket).isPresent()) {
            baseRate = BigDecimal.ONE.divide(forexMarket.getAskPrice(), 20, BigDecimal.ROUND_UP);
        } else {
            baseRate = BigDecimal.ONE.divide(market.getOpenPrice(), 20, BigDecimal.ROUND_UP);
        }
        TradeArea tradeArea = tradeAreaService.selectById(market.getTradeAreaId());
        // 报价货币
        if (market.getBuyCoinId().equals(tradeArea.getCoinId())) {
            baseRate = BigDecimal.ONE;
        }
        return baseRate;
    }

    /**
     * 从缓存中获取交易对数据
     *
     * @param symbol 交易对标识符
     * @return
     */
    private ForexMarketDTO queryForexMarketFromCache(String symbol) {
        String jsonString = (String) redisTemplate.opsForHash().get(REDIS_KEY_FOREX_MARKET, symbol);
        if (StringUtils.isEmpty(jsonString)) {
            return null;
        }
        return GsonUtil.convertObj(jsonString, ForexMarketDTO.class);
    }

}
